package com.rpoonolly.simplegame.core.aabb.tests;

import javax.vecmath.Vector2d;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

import com.rpoonolly.simplegame.core.CollisionDetector;
import com.rpoonolly.simplegame.core.CollisionResponder;
import com.rpoonolly.simplegame.core.Entity;
import com.rpoonolly.simplegame.core.aabb.AABBCollision;
import com.rpoonolly.simplegame.core.aabb.AABBCollisionManager;
import com.rpoonolly.simplegame.core.aabb.AABBCollisionSide;
import com.rpoonolly.simplegame.core.aabb.AABBEntity;

public class AABBCollisionResponseTest<E extends Entity> {
	private AABBEntity staticEntity, dynamicEntity;
	private Vector2d direction;
	private CollisionDetector<AABBEntity, AABBCollision> collisionDetector;
	private CollisionResponder<AABBCollision> collisionResponder;
	
	public AABBCollisionResponseTest() {
		AABBCollisionManager collisionMngr = new AABBCollisionManager();
		
		staticEntity = new AABBEntity(50, 50, 100, 100);
		dynamicEntity = new AABBEntity(0, 0, 25, 25);
		
		collisionDetector = collisionMngr;
		collisionResponder = collisionMngr;
		direction = new Vector2d();
	}
	
	@Before
	public void setup() {
		dynamicEntity.setX(0);
		dynamicEntity.setY(0);
		
		staticEntity.setX(50);
		staticEntity.setY(50);
		
		direction.x = 0;
		direction.y = 0;
	}

	@Test
	public void testRightCollision() {
		dynamicEntity.setY(100);
		direction.x = 100;
		
		detectAndRespond();
	}
	
	@Test
	public void testRightPartialCollision() {
		dynamicEntity.setY(100);
		direction.x = 30;
		
		detectAndRespond();
	}
	
	@Test
	public void testLeftCollision() {
		dynamicEntity.setY(100);
		dynamicEntity.setX(200);
		direction.x = -100;

		detectAndRespond();
	}
	
	@Test
	public void testLeftPartialCollision() {
		dynamicEntity.setY(100);
		dynamicEntity.setX(175);
		direction.x = -30;

		detectAndRespond();
	}
	
	@Test
	public void testDownCollision() {
		dynamicEntity.setX(100);
		dynamicEntity.setY(200);
		direction.y = -100;

		detectAndRespond();
	}
	
	@Test
	public void testDownPartialCollision() {
		dynamicEntity.setX(100);
		dynamicEntity.setY(175);
		direction.y = -30;

		detectAndRespond();
	}
	
	@Test
	public void testUpCollision() {
		dynamicEntity.setX(100);
		direction.y = 100;
		
		detectAndRespond();
	}
	
	@Test
	public void testUpPartialCollision() {
		dynamicEntity.setX(100);
		direction.y = 30;

		detectAndRespond();
	}
	
	private void detectAndRespond() {
		AABBCollision collision = collisionDetector.collisionDetect(staticEntity, dynamicEntity, direction);
		if (collision == null) Assert.fail("failed to create collision ");
		else {
			Vector2d correction = collisionResponder.collisionRespond(collision);
			AABBCollision collisionFixed = collisionDetector.collisionDetect(staticEntity, dynamicEntity, correction);
			Assert.assertNull("Collision: " + collisionFixed + "\noriginal-direction:" + direction, collisionFixed);
			
			dynamicEntity.setX((int) (dynamicEntity.getX() + correction.x));
			dynamicEntity.setY((int) (dynamicEntity.getY() + correction.y));
			AABBCollisionSide side = collision.getCollisionDirection();
			
			double distance;
			if (side == AABBCollisionSide.LEFT)
				distance = dynamicEntity.getX() - (staticEntity.getX() + staticEntity.getWidth());
			else if (side == AABBCollisionSide.RIGHT)
				distance = staticEntity.getX() - (dynamicEntity.getX() + dynamicEntity.getWidth());
			else if (side == AABBCollisionSide.DOWN)
				distance = dynamicEntity.getY() - (staticEntity.getY() + staticEntity.getHeight());
			else if (side == AABBCollisionSide.UP)
				distance = staticEntity.getY() - (dynamicEntity.getY() + dynamicEntity.getHeight());
			else
				distance = -1;
			
			Assert.assertEquals(distance, 0, .01);
		}
	}
}
